#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
upload_and_qrcode.py

图片上传到阿里云OSS并生成二维码下载链接的演示程序

功能流程：
1. 读取本地 example.jpg
2. 上传到阿里云 OSS 私有桶
3. 生成 1 小时有效的预签名下载 URL
4. 将 URL 编码为二维码并保存为 download_qr.png
"""

import os
import uuid
from pathlib import Path

import oss2
import qrcode
from dotenv import load_dotenv


def load_config():
    """加载配置信息"""
    load_dotenv(True)
    
    config = {
        'access_key_id': os.getenv('OSS_ACCESS_KEY_ID'),
        'access_key_secret': os.getenv('OSS_ACCESS_KEY_SECRET'),
        'endpoint': os.getenv('OSS_ENDPOINT'),
        'bucket_name': os.getenv('OSS_BUCKET_NAME'),
        'local_file': Path('example.jpg'),
        'qr_filename': Path('download_qr.png'),
        'url_expires': int(os.getenv('URL_EXPIRES', '3600'))  # 默认1小时
    }
    
    # 输出配置信息
    print("\n=== 配置信息 ===")
    print(f"OSS访问密钥ID: {'已设置' if config['access_key_id'] else '未设置'}")
    print(f"OSS访问密钥Secret: {'已设置' if config['access_key_secret'] else '未设置'}")
    print(f"OSS端点: {config['endpoint']}")
    print(f"OSS桶名: {config['bucket_name'] or '未设置'}")
    print(f"本地文件: {config['local_file']}")
    print(f"二维码文件: {config['qr_filename']}")
    print(f"URL有效期: {config['url_expires']}秒 ({config['url_expires'] // 3600}小时)")
    
    # 检查必需的配置项
    required_keys = ['access_key_id', 'access_key_secret', 'bucket_name']
    missing_keys = [key for key in required_keys if not config[key]]
    
    if missing_keys:
        raise ValueError(f"缺少必需的环境变量: {', '.join(missing_keys.upper())}")
    
    return config


def upload_to_oss(config):
    """上传文件到OSS并返回对象键"""
    # 检查本地文件是否存在
    if not config['local_file'].exists():
        raise FileNotFoundError(f"本地文件不存在: {config['local_file']}")
    
    # 生成唯一的对象键
    object_key = f"images/{uuid.uuid4().hex}{config['local_file'].suffix}"
    
    # 初始化OSS客户端
    auth = oss2.Auth(config['access_key_id'], config['access_key_secret'])
    bucket = oss2.Bucket(auth, config['endpoint'], config['bucket_name'])
    
    # 上传文件
    print(f"正在上传 {config['local_file']} → oss://{config['bucket_name']}/{object_key}")
    bucket.put_object_from_file(object_key, str(config['local_file']))
    print("文件上传成功！")
    
    return bucket, object_key


def generate_signed_url(bucket, object_key, expires, filename=None):
    """生成预签名下载URL"""
    headers = {}
    if filename:
        headers['Content-Disposition'] = f'attachment; filename="{filename}"'
    
    signed_url = bucket.sign_url(
        'GET',
        object_key,
        expires,
        headers=headers if headers else None
    )
    
    print(f"预签名URL生成成功，有效期: {expires // 3600}小时")
    print(f"下载链接: {signed_url}")
    
    return signed_url


def create_qr_code(url, output_path):
    """生成二维码图片"""
    qr = qrcode.QRCode(
        version=1,
        error_correction=qrcode.constants.ERROR_CORRECT_M,
        box_size=10,
        border=4,
    )
    
    qr.add_data(url)
    qr.make(fit=True)
    
    # 生成二维码图片
    img = qr.make_image(fill_color="black", back_color="white")
    img.save(output_path)
    
    print(f"二维码已保存到: {output_path.absolute()}")
    print("请用手机扫码下载图片！")


def main():
    """主函数"""
    try:
        # 加载配置
        config = load_config()
        
        # 上传文件到OSS
        bucket, object_key = upload_to_oss(config)
        
        # 生成预签名下载URL
        download_filename = f"downloaded_{config['local_file'].name}"
        signed_url = generate_signed_url(
            bucket, 
            object_key, 
            config['url_expires'],
            download_filename
        )
        
        # 生成二维码
        create_qr_code(signed_url, config['qr_filename'])
        
        print("\n=== 操作完成 ===")
        print(f"原文件: {config['local_file']}")
        print(f"OSS桶名: {config['bucket_name']}")
        print(f"OSS对象: {object_key}")
        print(f"二维码: {config['qr_filename']}")
        print(f"链接有效期: {config['url_expires'] // 3600}小时")
        
    except Exception as e:
        print(f"错误: {e}")
    

if __name__ == '__main__':
    main()